-- ------------------------------------------------------------------------
-- > lumStats (Kreoss @ Quel'Thalas EU) <
-- ------------------------------------------------------------------------
-- Credits: Lyn (LynStats), Katae (LiteStats) and Tekkub
-- ------------------------------------------------------------------------

	local st = CreateFrame("Button", "lumStats", UIParent)

-- ------------------------------------------------------------------------
-- > 0. Configuration and Media
-- ------------------------------------------------------------------------

	-- Media
	local font = "Fonts\\ARIALN.ttf"
	
	-- Modules
	local show_zone = true -- Location
	local show_clock = true -- Clock
	local show_fps = true -- Frame Rate
	local show_lag = true -- Latency
	local show_mail = true -- New Mail
	local show_bags = true -- Bag Space
	local show_dur = true -- Durability
	
	-- Config
	local fWidth = 430 -- Main Frame Width
	local fHeight = 14 -- Main Frame Height
	local fParent = "UIParent" -- Main Frame Parent
	local fParentPoint = "BOTTOM" -- Main Frame Parent Anchor
	local fPoint = "CENTER" -- Main Frame Set Point
	local fPosx = 0 -- Main Horizontal Position
	local fPosy = 8 -- Main Vertical Position
		
	local fontSize = 10 -- Font Size duh!
	local fontFlag = "THINOUTLINE" -- The Font Outline
	local fontShadow = true -- Font Shadow
	local tmargin = 4 -- Text Left and Right Margins
	
	local time24 = true -- If true show Time in 24H Format
	local nraddons = 20 -- Number of addons to show on the memory tooltip

-- ------------------------------------------------------------------------
-- > 1. Variables
-- ------------------------------------------------------------------------

	local zone, hour, mail, fps, lag, bags, dur
	local timer, slotsfree, memBefore, memAfter, memory, entry, BlizzMem, gotMail, lowdur = 0
	
	-- Copy Global functions
	local GetContainerNumFreeSlots, GetInventorySlotInfo, GetInventoryItemDurability = GetContainerNumFreeSlots, GetInventorySlotInfo, GetInventoryItemDurability
	local GetFramerate, GetMinimapZoneText, HasNewMail, GetNetStats = GetFramerate, GetMinimapZoneText, HasNewMail, GetNetStats
	local format, pairs, ipairs, collectgarbage, gcinfo, floor = string.format, pairs, ipairs, collectgarbage, gcinfo, math.floor
	
	-- Text Color
	local tColor = {r = 0.92, g = 0.92, b = 0.92, a = 1} -- Text Color
	local lColor = RAID_CLASS_COLORS[select(2, UnitClass("player"))] -- Label Class Colored
	
	local SLOTS = {}
	for _,slot in pairs({"Head", "Shoulder", "Chest", "Waist", "Legs", "Feet", "Wrist", "Hands", "MainHand", "SecondaryHand", "Ranged"}) do SLOTS[slot] = GetInventorySlotInfo(slot .. "Slot") end
	
-- ------------------------------------------------------------------------
-- > 2. Functions
-- ------------------------------------------------------------------------

	-- Hex Color
	local Hex
		do 
			Hex = function(color)
        	return format('|cff%02x%02x%02x', color.r * 255, color.g * 255, color.b * 255)
   		end
	end
	
	function Gradient(perc)
		perc = perc > 1 and 1 or perc < 0 and 0 or perc
		local seg, relperc = math.modf(perc*2)
		local r1,g1,b1,r2,g2,b2 = select(seg*3+1,1,0,0,1,1,0,1,1,1,0,0,0) -- R -> Y -> W
		local r,g,b = r1+(r2-r1)*relperc,g1+(g2-g1)*relperc,b1+(b2-b1)*relperc
		return format("|cff%02x%02x%02x",r*255,g*255,b*255),r,g,b
	end

	-- Fontstring Function
  	local createFontstring = function(fr, font, size, outline, shadow)
	
    	local fs = fr:CreateFontString(nil, "OVERLAY")
    	fs:SetFont(font, size, outline)
    	if shadow then fs:SetShadowColor(0,0,0,1) end
    	return fs
  	end
	
	-- Format Memory String (LynStats)
	local memFormat = function(num)
		if num > 1024 then
			return format("%.2f mb", (num / 1024))
		else
			return format("%.1f kb", floor(num))
		end
	end
	
	-- Time Format
	local timeFormat = function(t)
	
		local day, hour, minute, second = ChatFrame_TimeBreakDown(floor(t)) -- Blizzard Function
		
		if t >= 86400 then -- Days
			return format("%d|cff999999d|r", day)
		elseif t >= 3600 then -- Hours
			return format("%d|cff999999h|r %d|cff999999m|r", hour, minute)
		elseif t >= 60 then -- Minutes
			return format("%d|cff999999m|r", minute)
		elseif t >= 0 then -- Seconds
			return format("%d|cff999999s|r", second)
		end
	end
		
	-- Cool short number
	local shortFormat = function(num)
	
		if(num >= 1e6) then
			return (floor((num/1e6)*10 + 0.5))/10 .."|cffb3b3b3m"
		elseif(num >= 1e3) then
			return (floor((num/1e3)*10 + 0.5))/10 .."|cffb3b3b3k"
		else
			return num
		end
	end
	
	-- Ordering
	local AddonCompare = function(a, b)
		return a.memory > b.memory
	end
	
	-- ClearGarbage (LynStats)
	local ClearGarbage = function()
		UpdateAddOnMemoryUsage()
		memBefore = gcinfo()
		collectgarbage()
		UpdateAddOnMemoryUsage()
		memAfter = gcinfo()
		ChatFrame1:AddMessage(("%sGarbage Cleaned:|r "..memFormat(memBefore - memAfter)):format(Hex(lColor)))
	end
	
	-- Count Free Bags Free Slots 
	function st:bagsSlotsFree()
	
		local free = 0
		for i = 0, NUM_BAG_SLOTS do
			free = free + GetContainerNumFreeSlots(i)
		end
		return free
	end
	
	-- Calculates Lower Durability
	function st:Durability()

		local l = 1
		for slot,id in pairs(SLOTS) do
			local d, md = GetInventoryItemDurability(id)
			if d and md and md ~= 0 then
				l = math.min(d/md, l)
			end
		end

		return format("%s%d|r",Gradient(l),l*100)
	end
	
	-- Initialize Function
	function st:Init()
			
		self:SetWidth(fWidth)
		self:SetHeight(fHeight)
		self:SetPoint(fPoint, fParent, fParentPoint, fPosx, fPosy)
		
		self.lf = CreateFrame("Button", nil, self) -- Left Frame
		self.cf = CreateFrame("Button", nil, self) -- Center Frame
		self.rf = CreateFrame("Button", nil, self) -- Right Frame
		
		self.lf:SetHeight(fHeight)
		self.lf:SetPoint("LEFT", self, tmargin, 0)
		self.cf:SetHeight(fHeight)
		self.cf:SetPoint("CENTER", self, tmargin, 0)
		self.rf:SetHeight(fHeight)
		self.rf:SetPoint("RIGHT", self, -tmargin, 0)
		
		-- Create Left Text
		Ltext = createFontstring(self.lf, font, fontSize, fontFlag, fontShadow) 
		Ltext:SetPoint("LEFT", self.lf, tmargin, 0)
		Ltext:SetTextColor(tColor.r, tColor.g, tColor.b)
		-- Create Center Text
		Ctext = createFontstring(self.cf, font, fontSize, fontFlag, fontShadow) 
		Ctext:SetPoint("CENTER", self.cf, 0, 0)
		Ctext:SetTextColor(tColor.r, tColor.g, tColor.b)
		-- Create Right Text
		Rtext = createFontstring(self.rf, font, fontSize, fontFlag, fontShadow) 
		Rtext:SetPoint("RIGHT", self.rf, -tmargin, 0)
		Rtext:SetTextColor(tColor.r, tColor.g, tColor.b)
		
		self:SetScript("OnUpdate", self.Update)
		self.lf:SetScript("OnEnter", self.zoneTooltip)
		self.cf:SetScript("OnEnter", self.memTooltip)
		self.rf:SetScript("OnEnter", self.dateTooltip)		
		self.lf:SetScript("OnLeave", function() GameTooltip:Hide() end)
		self.cf:SetScript("OnLeave", function() GameTooltip:Hide() end)
		self.rf:SetScript("OnLeave", function() GameTooltip:Hide() end)
		self.lf:SetScript("OnClick", function() ToggleFrame(WorldMapFrame) end)
		self.cf:RegisterForClicks("AnyUp")
		self.cf:SetScript("OnClick", function(self,button) if button == "LeftButton" then ClearGarbage() elseif button == "RightButton" then OpenAllBags() end end)
		self.rf:SetScript("OnClick", function() ToggleCalendar() end)
	end
	
	-- Update Function
	function st:Update(elapsed)
	
		timer = timer + elapsed
		if timer > 1 then -- Updates each X seconds	
		
			-- Zone
			if show_zone then
				zone = GetMinimapZoneText()
			else
				zone = ''
			end
			
			-- Time
			if show_clock then
				if time24 then
					hour = date("%H:%M") -- Time 24H Format
				else
					hour = date("%I:%M |cff919191%p|r") -- Time 12H Format
				end
			else
				hour = ''
			end				
			
			-- Mail
			if show_mail then
				if gotMail then
					mail = ("  %sMail!|r"):format(Hex(lColor))
				else
					mail = ''
				end
			else
				mail = ''
			end
			
			-- FPS
			if show_fps then
				fps = GetFramerate()
				fps = (floor(fps).."%sfps|r   "):format(Hex(lColor))
			else
				fps = ''
			end
			
			-- Latency
			if show_lag then
				lag = select(3, GetNetStats())
				lag = (lag.."%sms|r   "):format(Hex(lColor))
			else
				lag = ''
			end
						
			-- Bags
			if show_bags then	
				bags = (slotsfree.."%sbag|r   "):format(Hex(lColor))			
			end
			
			-- Durability
			if show_dur then
				dur = (lowdur.."%sdur|r   "):format(Hex(lColor))
			end
			
			-- Show me the money!
			Ltext:SetText(zone) -- Left Anchored Text
			Ctext:SetText(fps..lag..bags..dur) -- Center Anchored Text
			Rtext:SetText(hour..mail) -- Right Anchored Text
			
			-- Frames Width
			self.lf:SetWidth(Ltext:GetStringWidth())
			self.cf:SetWidth(Ctext:GetStringWidth())
			self.rf:SetWidth(Rtext:GetStringWidth())
			
			timer = 0 -- Reset Timer
		end
	end
		
	-- Zone Tooltip
	function st:zoneTooltip()
	
		if UnitAffectingCombat('player') == nil then -- Don't Show in Combat
		GameTooltip:SetOwner(self, "ANCHOR_NONE")
		GameTooltip:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 0, 8)
		GameTooltip:AddLine("Zone", lColor.r, lColor.g, lColor.b)
		GameTooltip:AddLine(" ")
		for i=1,1 do -- Mudar para for=1,2 no CC para mostrar Tol Barad
			local _,mapName,isActive,_,startTime,_,status = GetWorldPVPAreaInfo(i)
			if(not isActive) then status = timeFormat(startTime) else status = "In Progress" end
			GameTooltip:AddDoubleLine(format("Next %s Battle:",mapName),status,1,0,0.42, 1,1,1)
		end
		GameTooltip:AddLine(" ")
		GameTooltip:AddLine("Click to open the World Map")
		GameTooltip:Show()
		end
	end
	
	
	-- Date Tooltip
	function st:dateTooltip()
	
		if UnitAffectingCombat('player') == nil then -- Don't Show in Combat
		GameTooltip:SetOwner(self, "ANCHOR_NONE")
		GameTooltip:SetPoint("BOTTOMRIGHT", self, "TOPRIGHT", 0, 8)
		GameTooltip:AddLine(date('%A, %d %B'), lColor.r, lColor.g, lColor.b)
		GameTooltip:AddLine(" ")
		GameTooltip:AddDoubleLine(gsub(TIMEMANAGER_TOOLTIP_LOCALTIME,':',''),GameTime_GetLocalTime(true),lColor.r, lColor.g, lColor.b, 1,1,1)
		GameTooltip:AddDoubleLine(gsub(TIMEMANAGER_TOOLTIP_REALMTIME,':',''),GameTime_GetGameTime(true),lColor.r, lColor.g, lColor.b, 1,1,1)
		GameTooltip:AddLine(" ")
		if(GetLatestThreeSenders()) then
			local s1, s2, s3 = GetLatestThreeSenders()
			local senders = {s1,s2,s3}
			for i, sender in ipairs(senders) do
				if sender == nil then break end
				if(i==1) then GameTooltip:AddDoubleLine("New mail from:", sender, 1, 0, 0.42, tColor.r, tColor.g, tColor.b)
				else GameTooltip:AddDoubleLine(" ", sender, 0, 0, 0, tColor.r, tColor.g, tColor.b) end
			end
		end
		GameTooltip:AddLine(" ")
		GameTooltip:AddLine("Click to show the Calendar")
		GameTooltip:Show()
		end
	end
	
	-- Memory Tooltip Function (LynStats)
	function st:memTooltip()
	
		if UnitAffectingCombat('player') == nil then -- Don't Show in Combat
		local addons, total, nr, name = {}, 0, 0
		GameTooltip:SetOwner(self, "ANCHOR_NONE")
		GameTooltip:SetPoint("BOTTOM", self, "TOP", 0, 8)
		BlizzMem = collectgarbage("count")
		UpdateAddOnMemoryUsage()
		GameTooltip:AddLine("Top "..nraddons.." AddOns", lColor.r, lColor.g, lColor.b)
		GameTooltip:AddLine(" ")
		for i = 1, GetNumAddOns(), 1 do
			if (GetAddOnMemoryUsage(i) > 0 ) then
				memory = GetAddOnMemoryUsage(i)
				entry = {name = GetAddOnInfo(i), memory = memory}
				table.insert(addons, entry)
				total = total + memory
			end
		end
		table.sort(addons, AddonCompare)
		for _, entry in pairs(addons) do
			if nr < nraddons then
				GameTooltip:AddDoubleLine(entry.name, memFormat(entry.memory), 1, 1, 1, 1, 1, 1)
				nr = nr+1
			end
		end
		GameTooltip:AddLine(" ")
		GameTooltip:AddDoubleLine("UI Memory usage", memFormat(total), lColor.r, lColor.g, lColor.b, lColor.r, lColor.g, lColor.b)
		GameTooltip:AddDoubleLine("Total incl. Blizzard", memFormat(BlizzMem), lColor.r, lColor.g, lColor.b, lColor.r, lColor.g, lColor.b)
		GameTooltip:AddLine(" ")
		GameTooltip:AddLine("Click to colect garbage")
		GameTooltip:AddLine("Right Click to open Bags")
		GameTooltip:Show()
		end
	end
		
	function st:ZONE_CHANGED_NEW_AREA(self,event,...)

		if event == "ZONE_CHANGED_NEW_AREA" and not WorldMapFrame:IsShown() then		
			SetMapToCurrentZone() -- Sets Map to Current Zone so Text Updates Correctly
		end
	end
	
	-- Bag Update
	function st:BAG_UPDATE(self,event,...)
	
		slotsfree = st:bagsSlotsFree()
	end
		
	function st:UPDATE_INVENTORY_DURABILITY(self,event,...)
		
		lowdur = st:Durability()
	end
	
	function st:UPDATE_PENDING_MAIL(self,event,...)
	
		gotMail = (HasNewMail() or nil)
	end
	
	function st:PLAYER_LOGIN(self,event,...)
	
		slotsfree = st:bagsSlotsFree()
		lowdur = st:Durability()
		gotMail = (HasNewMail() or nil)
	end
	
	function st:ADDON_LOADED(self,event,...)

		-- Events
		st:RegisterEvent("ZONE_CHANGED_NEW_AREA")
		st:RegisterEvent("PLAYER_LOGIN")
		st:RegisterEvent("BAG_UPDATE")  
		st:RegisterEvent("UPDATE_INVENTORY_DURABILITY")  
		st:RegisterEvent("UPDATE_PENDING_MAIL")  
	end
	
-- ------------------------------------------------------------------------
-- > 3. Calls
-- ------------------------------------------------------------------------
	
	st:Init() -- Begins the Magic!
	
-- ------------------------------------------------------------------------
-- > 4. Events
-- ------------------------------------------------------------------------

	st:SetScript("OnEvent", function(self, event, ...) if self[event] then return self[event](self, event, ...) end end)
	st:RegisterEvent("ADDON_LOADED")